package me.zhengjie.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.pojo.dto.*;
import me.zhengjie.pojo.dto.WcsFluentFrameNgs;
import me.zhengjie.pojo.entity.*;
import me.zhengjie.pojo.vo.AllFloorVo;
import me.zhengjie.pojo.vo.QueryEmptyMaterialBoxVo;
import me.zhengjie.pojo.vo.QueryEmptyMaterialBoxVoList;
import me.zhengjie.pojo.vo.ReturnVo;
import me.zhengjie.service.InterfaceService;
import me.zhengjie.sqlservice.*;
import me.zhengjie.tcp.FluentFrame;
import me.zhengjie.utility.state.TaskStatus;
import me.zhengjie.utility.state.TaskType;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class InterfaceServiceImpl implements InterfaceService {
    private final WcsFluentFrameConfigService wcsFluentFrameConfigService;

    private final WcsInboundMissionService wcsInboundMissionService;

    private final WcsLineEdgeWarehouseService wcsLineEdgeWarehouseService;

    private final WcsFluentFrameNgService wcsFluentFrameNgService;

    private final FluentFrame fluentFrame;

    private final WcsFluentFrameOutboundDetailsService wcsFluentFrameOutboundDetailsService;

    @Override
    public ReturnVo fluentFrameMode(HttpServletRequest request) {
        String clientIp = getClientIp(request);
        log.info("当前设备ip：{}",clientIp);
        List<WcsFluentFrameConfig> wcsFluentFrameConfigList = wcsFluentFrameConfigService.selectDeviceIp(clientIp);
        if (!wcsFluentFrameConfigList.isEmpty()){
            WcsFluentFrameConfig wcsFluentFrameConfig = wcsFluentFrameConfigList.get(0);
            Integer mode = wcsFluentFrameConfig.getMode();
            String workstation = wcsFluentFrameConfig.getWorkstation();
            FluentFrameModeDto fluentFrameModeDto = new FluentFrameModeDto();
            fluentFrameModeDto.setMode(mode);
            fluentFrameModeDto.setWorkstation(workstation);
            return ReturnVo.OK(fluentFrameModeDto);
        }
        return ReturnVo.ng("未找到"+clientIp +"设备数据");
    }

    @Transactional
    @Override
    public ReturnVo updateMode(HttpServletRequest request, Integer mode) {
        String clientIp = getClientIp(request);
        log.info("修改模式当前设备ip：{}",clientIp);
        List<WcsFluentFrameConfig> wcsFluentFrameConfigList = wcsFluentFrameConfigService.selectDeviceIp(clientIp);
        if (!wcsFluentFrameConfigList.isEmpty()){
           boolean b = wcsFluentFrameConfigService.updateMode(clientIp,mode);
           if (!b){
               log.error("修改设备id"+clientIp+"模式失败");
               throw new RuntimeException("修改设备id"+clientIp+"模式失败");
           }
           return ReturnVo.OK();
        }
        return ReturnVo.ng("未找到"+clientIp +"设备数据");
    }

    @Override
    public ReturnVo queryEmptyMaterialBox(HttpServletRequest request, Integer page, Integer size) {
        String clientIp = getClientIp(request);
        log.info("查询空料箱ip：{},参数：{},{}",clientIp,page,size);
        List<WcsFluentFrameConfig> wcsFluentFrameConfigList = wcsFluentFrameConfigService.selectDeviceIp(clientIp);
        if (!wcsFluentFrameConfigList.isEmpty()){
            List<String> sourceList = wcsFluentFrameConfigList.stream().map(WcsFluentFrameConfig::getInboundStorageCode).distinct().collect(Collectors.toList());
            //分页查询
            List<WcsInboundMission> wcsInboundMissionList = wcsInboundMissionService.queryEmptyMaterialBox(sourceList, TaskType.EMPTY_MATERIAL_BOX_STORAGE.getStatus(),page,size);
            log.info("查询分页数据：{}",wcsInboundMissionList);
            Integer wcsInboundCound = wcsInboundMissionService.queryEmptyMaterialBoxCount(sourceList, TaskType.EMPTY_MATERIAL_BOX_STORAGE.getStatus());
            ArrayList<QueryEmptyMaterialBoxVo> queryEmptyMaterialBoxVoArrayList = new ArrayList<>();
            QueryEmptyMaterialBoxVoList queryEmptyMaterialBoxVoList = new QueryEmptyMaterialBoxVoList();
            for (WcsInboundMission wcsInboundMission : wcsInboundMissionList) {
                QueryEmptyMaterialBoxVo queryEmptyMaterialBoxVo = new QueryEmptyMaterialBoxVo();
                BeanUtils.copyProperties(wcsInboundMission,queryEmptyMaterialBoxVo);
                queryEmptyMaterialBoxVoArrayList.add(queryEmptyMaterialBoxVo);
            }
            queryEmptyMaterialBoxVoList.setQueryEmptyMaterialBoxVoList(queryEmptyMaterialBoxVoArrayList);
            queryEmptyMaterialBoxVoList.setTotal(wcsInboundCound);
            return ReturnVo.OK(queryEmptyMaterialBoxVoList);
        }
        return ReturnVo.ng("当前ip" + clientIp +"未查询到数据");
    }

    @Override
    public ReturnVo queryFloor(String floor) {
        List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouseList = wcsLineEdgeWarehouseService.selectFloor(floor);
        return ReturnVo.OK(wcsLineEdgeWarehouseList);
    }

    @Override
    public ReturnVo emptyTrayQuantity(EmptyTrayQuantityDto emptyTrayQuantityDto) {
        String storageCode = emptyTrayQuantityDto.getStorageCode();
        Integer quantity = emptyTrayQuantityDto.getQuantity();
        if (quantity <=0){
            return ReturnVo.ng("提交空托盘数量异常");
        }
        WcsLineEdgeWarehouse wcsLineEdgeWarehouse = wcsLineEdgeWarehouseService.selectStorageCode(storageCode);
        if (wcsLineEdgeWarehouse !=null  && wcsLineEdgeWarehouse.getCcdStatus() == 1 && (wcsLineEdgeWarehouse.getStatus() == 4 || wcsLineEdgeWarehouse.getStatus() == 5) ) {
            boolean b = wcsLineEdgeWarehouseService.updateEmptyTrayQuantityStatus(storageCode,quantity, TaskStatus.LINE_EDGE_WAREHOUSE_EMPTY_PALLET.getStatus());
            if (!b){
                throw new RuntimeException("数据库异常,修改数据失败");
            }
            return ReturnVo.OK();
        }
        return ReturnVo.ng("储位被禁用或储位无栈板,提交失败");
    }

    @Override
    public ReturnVo lineEdgeWarehouseModify(LineEdgeWarehouseModifyDto lineEdgeWarehouseModifyDto) {
        String storageCode = lineEdgeWarehouseModifyDto.getStorageCode();
        Integer isLock = lineEdgeWarehouseModifyDto.getIsLock();
        WcsLineEdgeWarehouse wcsLineEdgeWarehouse = wcsLineEdgeWarehouseService.selectStorageCodeDoesItExist(storageCode);
        if (wcsLineEdgeWarehouse !=null){
            boolean b = wcsLineEdgeWarehouseService.updateIslocck(storageCode,isLock);
            return ReturnVo.OK();
        }
        return ReturnVo.ng("未查询到线边储位");
    }

    @Override
    public ReturnVo queryAvailableFloor(String floor) {
        List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouseList = wcsLineEdgeWarehouseService.queryAvailableFloor(floor);
        return ReturnVo.OK(wcsLineEdgeWarehouseList);
    }

    @Override
    public ReturnVo queryFloorAll() {
        List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouseList = wcsLineEdgeWarehouseService.selectAll();
        List<String> collect = wcsLineEdgeWarehouseList.stream().map(WcsLineEdgeWarehouse::getFloor).distinct().collect(Collectors.toList());
        ArrayList<AllFloorVo> floorList = new ArrayList<>();
        for (String floor : collect) {
            AllFloorVo allFloorVo = new AllFloorVo();
            allFloorVo.setValue(floor);
            switch (floor){
                case  "M1":{
                    allFloorVo.setText("车间三1楼");
                    break;
                }
                case "M2":{
                    allFloorVo.setText("车间三2楼");
                    break;
                }
                case "M3":{
                    allFloorVo.setText("车间三3楼");
                    break;
                }
                case "M4":{
                    allFloorVo.setText("车间三4楼");
                    break;
                }
                case "M5":{
                    allFloorVo.setText("车间三5楼");
                    break;
                }
                case "F1":{
                    allFloorVo.setText("F栋1楼");
                    break;
                }
                case "F2":{
                    allFloorVo.setText("F栋2楼");
                    break;
                }
                case "F3":{
                    allFloorVo.setText("F栋3楼");
                    break;
                }
                case "F4":{
                    allFloorVo.setText("F栋4楼");
                    break;
                }
                case "F5":{
                    allFloorVo.setText("F栋5楼");
                    break;
                }
                case "F6":{
                    allFloorVo.setText("F栋6楼");
                    break;
                }
                case "F7":{
                    allFloorVo.setText("F栋7楼");
                    break;
                }
            }
            floorList.add(allFloorVo);
        }
        return ReturnVo.OK(floorList);
    }

    @Override
    @Transactional
    public ReturnVo sweepStorage(HttpServletRequest request, SweepStorageDto sweepStorageDto) {
        String storageCode = sweepStorageDto.getStorageCode();
        String direction = sweepStorageDto.getDirection();
        if (storageCode.isEmpty() || direction.isEmpty()) {
            return ReturnVo.ng("传参为NULL");
        }
        String clientIp = getClientIp(request);
        boolean b = wcsFluentFrameConfigService.updateSweepStorage(clientIp,direction,storageCode);
        if (!b){
            throw new RuntimeException("数据库异常修改失败");
        }
        return ReturnVo.OK();
    }

    @Override
    public ReturnVo fluentFrameNg(HttpServletRequest request) {
        String clientIp = getClientIp(request);
        List<WcsFluentFrameConfig> wcsFluentFrameConfigList = wcsFluentFrameConfigService.selectStorageRegion(clientIp);
        log.info("查询NG电脑IP：{},根据IP查询到数据：{}",clientIp,wcsFluentFrameConfigList);
        WcsFluentFrameNgDto wcsFluentFrameNgDto = new WcsFluentFrameNgDto();
        for (WcsFluentFrameConfig wcsFluentFrameConfig : wcsFluentFrameConfigList) {
            Integer sortingAddress = wcsFluentFrameConfig.getSortingAddress();
            String region = wcsFluentFrameConfig.getRegion();
            Integer unitId = wcsFluentFrameConfig.getUnitId();
            Integer sortingReadingFinish = wcsFluentFrameConfig.getSortingReadingFinish();
            Integer sortingReadAddress = wcsFluentFrameConfig.getSortingReadAddress();
            String direction = wcsFluentFrameConfig.getDirection();
            Integer readHoldingRegisters = fluentFrame.readHoldingRegisters(region, sortingReadingFinish, unitId);
            Integer sortingStatus = fluentFrame.readHoldingRegisters(region, sortingAddress, unitId);
            if (sortingStatus != null && readHoldingRegisters !=null &&sortingStatus == 1 && readHoldingRegisters == 1){
                String containerCode = fluentFrame.readHoldingRegistersString(region, sortingReadAddress, unitId);
                List<me.zhengjie.pojo.entity.WcsFluentFrameNg> wcsFluentFrameNgList = wcsFluentFrameNgService.selectContainerCode(containerCode);
                if (!wcsFluentFrameNgList.isEmpty()){
                    me.zhengjie.pojo.entity.WcsFluentFrameNg wcsFluentFrameNg = wcsFluentFrameNgList.get(0);
                    WcsFluentFrameNgs wcsFluentFrameNg1 = new WcsFluentFrameNgs();
                    BeanUtils.copyProperties(wcsFluentFrameNg,wcsFluentFrameNg1);
                    wcsFluentFrameNg1.setDirection(direction);
                    if (TaskType.DIRECTION.getMessage().equals(direction)){
                        wcsFluentFrameNgDto.setLeft(wcsFluentFrameNg1);
                    }else if (TaskType.DIRECTION_RIGHT.getMessage().equals(direction)){
                        wcsFluentFrameNgDto.setRight(wcsFluentFrameNg1);
                    }
                }
            }
        }
        return ReturnVo.OK(wcsFluentFrameNgDto);
    }

    @Override
    public ReturnVo fluentFrameOutbound(HttpServletRequest request) {
        String clientIp = getClientIp(request);
        List<WcsFluentFrameConfig> wcsFluentFrameConfigList = wcsFluentFrameConfigService.selectStorageRegion(clientIp);
        FluentFrameOutboundDto fluentFrameOutboundDto = new FluentFrameOutboundDto();
        for (WcsFluentFrameConfig wcsFluentFrameConfig : wcsFluentFrameConfigList) {
            Integer sortingAddress = wcsFluentFrameConfig.getSortingAddress();
            String region = wcsFluentFrameConfig.getRegion();
            Integer unitId = wcsFluentFrameConfig.getUnitId();
            Integer sortingReadingFinish = wcsFluentFrameConfig.getSortingReadingFinish();
            Integer sortingReadAddress = wcsFluentFrameConfig.getSortingReadAddress();
            String direction = wcsFluentFrameConfig.getDirection();
            Integer readHoldingRegisters = fluentFrame.readHoldingRegisters(region, sortingReadingFinish, unitId);
            Integer sortingStatus = fluentFrame.readHoldingRegisters(region, sortingAddress, unitId);
            if (sortingStatus != null &&readHoldingRegisters !=null && sortingStatus == 1 && readHoldingRegisters == 1){
                String containerCode = fluentFrame.readHoldingRegistersString(region, sortingReadAddress, unitId);
                WcsFluentFrameOutboundDetails wcsFluentFrameOutboundDetails = wcsFluentFrameOutboundDetailsService.selectContainerCode(containerCode);
                if (wcsFluentFrameOutboundDetails != null){
                    FluentFrameOutbound fluentFrameOutbound = new FluentFrameOutbound();
                    fluentFrameOutbound.setContainerCode(containerCode);
                    fluentFrameOutbound.setDirection(direction);
                    if (TaskType.DIRECTION.getMessage().equals(direction)){
                        fluentFrameOutboundDto.setLeft(fluentFrameOutbound);
                    }else if (TaskType.DIRECTION_RIGHT.getMessage().equals(direction)){
                        fluentFrameOutboundDto.setRight(fluentFrameOutbound);
                    }
                }
            }
        }
        return ReturnVo.OK(fluentFrameOutboundDto);
    }


    /**
     * 通用获取客户端真实 IP 的工具方法
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}
